package org.linitly.boot.base.utils.auth.strategy;

import io.jsonwebtoken.ExpiredJwtException;
import org.apache.commons.lang3.StringUtils;
import org.linitly.boot.base.enums.ResultEnum;
import org.linitly.boot.base.exception.CommonException;
import org.linitly.boot.base.utils.bean.SpringBeanUtil;
import org.linitly.boot.base.utils.jwt.AbstractJwtUtil;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @author: linitly
 * @date: 2021/5/24 17:25
 * @descrption: 单token模式，可自动续期
 */
public class SingleTokenRenewModule extends SingleTokenModule {

    private static volatile SingleTokenRenewModule singleTokenRenewModule;

    private SingleTokenRenewModule(AbstractJwtUtil jwtUtil) {
        super(jwtUtil);
    }

    public static SingleTokenRenewModule getInstance(AbstractJwtUtil jwtUtil) {
        if (singleTokenRenewModule == null) {
            synchronized (SingleTokenRenewModule.class) {
                if (singleTokenRenewModule == null) {
                    singleTokenRenewModule = new SingleTokenRenewModule(jwtUtil);
                }
            }
        }
        return singleTokenRenewModule;
    }

    @Override
    public void interceptorValid(String tokenResponseHeadKey) {
        HttpServletRequest request = SpringBeanUtil.getRequest();
        String token = jwtUtil.getToken(request);
        if (StringUtils.isBlank(token)) {
            throw new CommonException(ResultEnum.UNAUTHORIZED);
        }
        try {
            jwtUtil.parseToken(token);
        } catch (ExpiredJwtException e) {
            validExpiredToken(token);
            // 设置新token
            generateNewToken(tokenResponseHeadKey);
            return;
        }
        validToken(token);
    }

    @Override
    public void validExpiredToken(String token) {
        String userId = getUserId();
        String lastExpiredToken = auth.getLastExpiredToken(userId);
        if (StringUtils.isBlank(lastExpiredToken) || !token.equals(lastExpiredToken)) {
            auth.setLastExpiredToken(userId, token);
            return;
        }
        throw new CommonException(ResultEnum.LOGIN_FAILURE);
    }

    @Override
    public void generateNewToken(String tokenResponseHeadKey) {
        String userId = getUserId();
        String newToken = jwtUtil.generateToken(userId);
        auth.newTokenRedisSet(userId, newToken);
        SpringBeanUtil.getResponse().setHeader(tokenResponseHeadKey, newToken);
    }
}
